<?php

class package{

	var $package_id;
	var $package;
	var $source;
	var $destination;
	var $options;

	var $filecount = 0;

	var $js_file_count = 0;
	var $js_size_start = 0;
	var $js_size_end = 0;

	var $css_file_count = 0;
	var $css_size_start = 0;
	var $css_size_end = 0;


	var $skipped_js_count = 0;


	function package($cmd){
		global $config;

		$id = $_REQUEST['id'];
		if( !isset($config['packages'][$id]) ){
			message('Invalid request.');
			return false;
		}
		$this->package_id = $id;
		$this->package = $config['packages'][$id];
		$this->source = rtrim($this->package['source'],'/');
		$this->package['destination'] = rtrim($this->package['destination'],'/');
		$this->SetOptions();


		//check destination folder
		if( !file_exists($this->source) ){
			message('Source does not exist.');
			return false;
		}

		if( !file_exists($this->package['destination']) ){
			message('Destination does not exist.');
			return false;
		}
		if( !is_writable($this->package['destination']) ){
			message('Destination is not writable.');
			return false;
		}

		switch($cmd){

			case 'min_project':
				$this->MinimizePackage();
			break;
		}

		$this->CreatePackagePrompt();
	}



	/**
	 *
	 * Package Functions
	 *
	 */
	function CreatePackagePrompt(){
		global $config;

		$i = 0;
		$folder = $this->package['name'];
		do{
			if( $i > 0 ){
				$folder = $this->package['name'].'('.$i.')';
			}
			$full_dest = $this->package['destination'].'/'.$folder;
			$i++;

		}while( file_exists($full_dest) );


		echo '<form method="post" action="">';
		echo '<input type="hidden" name="id" value="'.htmlspecialchars($this->package_id).'" />';
		echo '<table class="bordered" cellspacing="0" cellpadding="0">';
		echo '<tr>';
			echo '<th colspan="2">';
			echo $this->package['name'];
			echo '</th>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>';
			echo 'Source ';
			echo '</td>';
			echo '<td>';
			echo '<tt>';
			echo htmlspecialchars($this->source);
			echo '</tt>';
			echo '</td>';
			echo '</tr>';
		echo '<tr>';
			echo '<td>';
			echo 'Destination ';
			echo '</td>';
			echo '<td>';
			echo '<tt>';
			echo htmlspecialchars($this->package['destination']);
			echo '</tt>';
			echo '/<input type="text" name="folder" value="'.htmlspecialchars($folder).'"/>';

			echo '</td>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>';
			echo 'CSS Options ';
			echo '</td>';
			echo '<td>';

			echo '<label>';
			echo '<input type="hidden" name="min_css" value="" />';
			echo '<input type="checkbox" name="min_css" value="min_css" '. ( $this->options['min_css'] ? 'checked="checked"' : '' ).'/>';
			echo ' Minimize CSS';
			echo '</label>';

			echo ' <br/> ';

			echo '<label>';
			echo '<input type="hidden" name="css_full" value="" />';
			echo '<input type="checkbox" name="css_full" value="css_full" '. ( $this->options['css_full'] ? 'checked="checked"' : '' ).'/>';
			echo ' Add {$filename}-full.css';
			echo '</label>';

			echo '</td>';
			echo '</tr>';



		echo '<tr>';
			echo '<td>';
			echo 'JS Options ';
			echo '</td>';
			echo '<td>';

			echo '<label>';
			echo '<input type="hidden" name="min_js" value="" />';
			echo '<input type="checkbox" name="min_js" value="min_js" '. ( $this->options['min_js'] ? 'checked="checked"' : '' ).'/>';
			echo ' Minimize JS ';
			echo '</label>';

			echo ' <br/> ';

			echo '<label>';
			echo '<input type="hidden" name="js_full" value="" />';
			echo '<input type="checkbox" name="js_full" value="js_full" '. ( $this->options['js_full'] ? 'checked="checked"' : '' ).'/>';
			echo ' Add {$filename}-full.js';
			echo '</label>';


			echo '</td>';
			echo '</tr>';
		echo '<tr>';
			echo '<td>';
			echo '</td>';
			echo '<td>';
			echo ' <input type="hidden" name="cmd" value="min_project" />';
			echo ' <input type="submit" name="" value="Minimize" />';
			echo ' &nbsp; <input type="submit" name="cmd" value="Cancel" />';
			echo '</td>';
			echo '</tr>';
		echo '</table>';
		echo '</form>';

		return true;
	}


	function MinimizePackage(){
		global $config;

		$_POST += array('folder'=>'');

		$full_dest = $this->package['destination'].'/'.$_POST['folder'];

		if( !file_exists($this->package['destination']) ){
			message('Oops, <em>'.htmlspecialchars($this->package['destination']).'</em> does not exist.');
			return;
		}
		if( file_exists($full_dest) ){
			message('The folder <em>'.$_POST['folder'].'</em>  alread exists in your destination.');
			return;
		}

		if( !$this->CopyDir($this->source,$full_dest) ){
			message('Oops, the process was not completed.');
		}

		echo '<table class="bordered" cellpadding="0" cellspacing="0">';
		echo '<tr>';
			echo '<th colspan="2">';
			echo 'Stats ';
			echo '</th>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>';
			echo 'Destination ';
			echo '</td>';
			echo '<td>';
			echo $full_dest;
			echo '</td>';
			echo '</tr>';
		echo '<tr>';
			echo '<td>';
			echo 'Files Copied ';
			echo '</td>';
			echo '<td>';
			echo number_format($this->filecount);
			echo '</td>';
			echo '</tr>';

		echo '<th colspan="2">';
			echo 'Javascript Files ';
			echo '</th>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>Files Minimized </td>';
			echo '<td>';
			echo number_format($this->js_file_count);
			echo '</td>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>Original Size </td>';
			echo '<td>';
			echo number_format($this->js_size_start).' bytes';
			echo '</td>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>Minimized Size </td>';
			echo '<td>';
			echo number_format($this->js_size_end).' bytes';
			echo '</td>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>Reduction</td>';
			echo '<td>';
			$percent = 0;
			if( $this->js_size_start > 0 ){
				$percent = ($this->js_size_start - $this->js_size_end) / $this->js_size_start;
			}
			echo (number_format($percent,2)*100).'%';
			echo '</td>';
			echo '</tr>';


		if( count($this->skipped_js_count) ){
			echo '<tr>';
				echo '<td>';
				echo 'Skipped ';
				echo '</td>';
				echo '<td>';
				echo number_format($this->skipped_js_count);
				echo '</td>';
				echo '</tr>';
		}


		echo '<th colspan="2">CSS Files </th></tr>';

		echo '<tr>';
			echo '<td>Files Minimized </td>';
			echo '<td>';
			echo number_format($this->css_file_count);
			echo '</td>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>Original Size </td>';
			echo '<td>';
			echo number_format($this->css_size_start).' bytes';
			echo '</td>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>Minimized Size </td>';
			echo '<td>';
			echo number_format($this->css_size_end).' bytes';
			echo '</td>';
			echo '</tr>';

		echo '<tr>';
			echo '<td>Reduction</td>';
			echo '<td>';
			$percent = 0;
			if( $this->css_size_start > 0 ){
				$percent = ($this->css_size_start - $this->css_size_end) / $this->css_size_start;
			}
			echo (number_format($percent,2)*100).'%';
			echo '</td>';
			echo '</tr>';

		echo '</table>';


	}

	function SetOptions(){
		global $config;
		$this->options = array();


		//avoid types
		$this->options['avoid_types'] = array();
		$types = explode(' ',$config['ignore_types']);
		foreach($types as $type){
			$type = trim($type,"\n\r\t\0\x0B. ");
			if( empty($type) ){
				continue;
			}
			$this->options['avoid_types']['.'.$type] = true;
		}

		//ignore_prefix
		$this->options['ignore_prefix'] = array();
		$prefixes = explode(' ',$config['ignore_prefix']);
		foreach($prefixes as $prefix){
			$prefix = trim($prefix,"\n\r\t\0\x0B ");
			if( empty($prefix) ){
				continue;
			}
			$this->options['ignore_prefix'][$prefix] = $prefix;
		}


		//noshrink
		if( empty($this->package['noshrink']) ){
			$this->options['noshrink'] = false;
		}else{

			$noshrink_paths = explode("\n",$this->package['noshrink']);
			foreach($noshrink_paths as $path){
				$path = trim($path);
				if( !empty($path) ){
					$this->options['noshrink_paths'][] = $path;
					$this->options['noshrink'] = true;
				}
			}
		}

		//min css
		$_POST += array('min_css'=>'min_css');
		if( empty($_POST['min_css']) ){
			$this->options['min_css'] = false;
		}else{
			$this->options['min_css'] = true;
		}

		//full css
		$_POST += array('css_full'=>'');
		if( empty($_POST['css_full']) ){
			$this->options['css_full'] = false;
		}else{
			$this->options['css_full'] = true;
		}


		//min js
		$_POST += array('min_js'=>'min_js');
		if( empty($_POST['min_js']) ){
			$this->options['min_js'] = false;
		}else{
			$this->options['min_js'] = true;
		}


		//full js
		$_POST += array('js_full'=>'');
		if( empty($_POST['js_full']) ){
			$this->options['js_full'] = false;
		}else{
			$this->options['js_full'] = true;
		}


	}


	function CopyDir($fromDir,$toDir){
		if( !is_dir($fromDir) ){
			trigger_error('Not a directory: '.$fromDir);
			return false;
		}

		if( !is_dir($toDir) ){
			if( !@mkdir($toDir) ){
				message('Could not make directory <em>'.$toDir.'</em>.');
				$this->filecount++;
				return false;
			}
			chmod($toDir,0777);
		}

		$dh = opendir($fromDir);
		if( !$dh ){
			message('Could not open directory <em>'.$fromDir.'</em>.');
			return false;
		}

		while( ($fileName = readdir($dh)) !== false){


			if( $fileName == '.' ){
				continue;
			}
			if( $fileName == '..' ){
				continue;
			}

			$fullFrom = $fromDir.'/'.$fileName;
			$fullTo = $toDir.'/'.$fileName;
			$type = $this->GetFileType($fileName);

			if( !$this->CheckFile($fileName,$type) ){
				continue;
			}


			if( is_link($fullFrom) ){
				continue;
			}

			if( is_dir($fullFrom) ){
				if( !$this->CopyDir($fullFrom,$fullTo) ){
					return false;
				}
				continue;
			}

			if( !$this->CopyFile($fullFrom,$fullTo,$type) ){
				return false;
			}

		}

		return true;
	}

	function CheckFile($filename,$type){

		//by file type
		if( isset($this->options['avoid_types'][$type]) && $this->options['avoid_types'][$type] ){
			return false;
		}

		//by file name
		foreach($this->options['ignore_prefix'] as $prefix){
			if( strpos($filename,$prefix) === 0 ){
				return false;
			}
		}

		return true;
	}

	//check for noshrink paths
	function CanShrink($from){
		if( $this->options['noshrink'] ){
			foreach($this->options['noshrink_paths'] as $path){
				if( strpos($from,$path) === 0 ){
					return false;
				}
			}
		}
		return true;
	}



	function CopyFile($from,$to,$type){
		set_time_limit(30);


		$this->filecount++;

		$result = true;
		switch($type){
			case '.js':
				if( $this->CanShrink($from) ){
					if( $this->options['min_js'] ){
						return $this->CopyJS($from,$to);
					}else{
						break;
					}
				}else{
					$this->skipped_js_count++;
				}
			break;

			case '.css':
				if( $this->options['min_css'] && $this->CanShrink($from) ){
					return $this->CopyCSS($from,$to);
				}
			break;
		}
		if( copy($from,$to) ){
			chmod($to,0777);
			return true;
		}
		return false;
	}

	function CopyCSS($fromNew,$toNew){
		$buffer = file_get_contents($fromNew);

		//make a full copy first
		if( $this->options['css_full'] ){
			$full_file = substr($toNew,0,-4).'-full.css';
			if( !$this->SaveContents($full_file,$buffer) ) return false;
		}


		$this->css_size_start += strlen($buffer);
		$buffer = phpproject::MinCss($buffer);
		$this->css_file_count++;
		$this->css_size_end += strlen($buffer);

		return $this->SaveContents($toNew,$buffer);
	}


	function CopyJS($from,$to){
		global $project;


		if( $this->options['js_full'] ){
			$buffer = file_get_contents($from);
			$full_file = substr($to,0,-3).'-full.js';
			if( !$this->SaveContents($full_file,$buffer) ) return false;
		}

		$result = $project->MinimizeJSFile($from,$this->source);
		if( $result === false ){
			return false;
		}

		$this->js_file_count++;

		if( (int)$result['statistics']['originalSize'] <= (int)$result['statistics']['compressedSize'] ){
			//message($from);
			//message('minimized file actually bigger than original: orig: '.number_format($result['statistics']['originalSize']).' min: '.number_format($result['statistics']['compressedSize']));
			$this->js_size_start += (int)$result['statistics']['originalSize'];
			$this->js_size_end += (int)$result['statistics']['originalSize'];
			$contents = file_get_contents($from);
		}else{
			$this->js_size_start += (int)$result['statistics']['originalSize'];
			$this->js_size_end += (int)$result['statistics']['compressedSize'];
			$contents  = $result['compiledCode'];
		}

		return $this->SaveContents($to,$contents);
	}

	function SaveContents($file,$contents){
		$fh = fopen($file,'w');
		if( !$fh ) return false;
		if( !fwrite($fh,$contents) ){
			fclose($fh);
			return false;
		}
		fclose($fh);
		chmod($file,0777);
		return true;
	}

	function GetFileType($file){
		$type = '';
		$dotSpot = strrpos($file,'.');
		if( $dotSpot !== false ){
			$type = substr($file,$dotSpot);
		}
		return strtolower($type);
	}

}



